package ffte.test.types

import spinal.core._
import spinal.core.sim._
import ffte.types._

/**
 * FixComplex正确测试套件
 * 使用正确的字段名称：re和im
 */
class FixComplexCorrectTest extends Component {
  val io = new Bundle {
    val real_in = in SInt(16 bits)
    val imag_in = in SInt(16 bits)
    val real_out = out SInt(16 bits)
    val imag_out = out SInt(16 bits)
    val enable = in Bool()
  }

  val testArea = new Area {
    // 创建FixComplex实例
    val complex1 = FixComplex(16, -8)  // 16位总宽，8位小数
    val complex2 = FixComplex(16, -8)
    val result = FixComplex(16, -8)
    
    // 连接输入 - 使用正确的字段名称：re和im
    complex1.re.d.raw := io.real_in
    complex1.im.d.raw := io.imag_in
    complex2.re.d.raw := io.real_in
    complex2.im.d.raw := io.imag_in
    
    // 复数加法
    val sum = complex1 + complex2
    
    // 根据使能信号选择输出
    when(io.enable) {
      result.re.d.raw := sum.re.d.raw
      result.im.d.raw := sum.im.d.raw
    } otherwise {
      result.re.d.raw := complex1.re.d.raw
      result.im.d.raw := complex1.im.d.raw
    }
    
    // 连接输出
    io.real_out := result.re.d.raw
    io.imag_out := result.im.d.raw
  }
}

/**
 * 复数乘法测试
 */
class FixComplexMultCorrectTest extends Component {
  val io = new Bundle {
    val real1 = in SInt(16 bits)
    val imag1 = in SInt(16 bits)
    val real2 = in SInt(16 bits)
    val imag2 = in SInt(16 bits)
    val real_out = out SInt(32 bits)  // 乘法需要更大位宽
    val imag_out = out SInt(32 bits)
  }

  val multArea = new Area {
    // 创建复数实例
    val a = FixComplex(16, -8)
    val b = FixComplex(16, -8)
    
    // 连接输入
    a.re.d.raw := io.real1
    a.im.d.raw := io.imag1
    b.re.d.raw := io.real2
    b.im.d.raw := io.imag2
    
    // 复数乘法： (a+bi)(c+di) = (ac-bd) + (ad+bc)i
    val product = a * b
    
    // 连接输出
    io.real_out := product.re.d.raw
    io.imag_out := product.im.d.raw
  }
}

/**
 * 复数共轭测试
 */
class FixComplexConjugateCorrectTest extends Component {
  val io = new Bundle {
    val real_in = in SInt(16 bits)
    val imag_in = in SInt(16 bits)
    val real_out = out SInt(16 bits)
    val imag_out = out SInt(16 bits)
  }

  val conjArea = new Area {
    val input = FixComplex(16, -8)
    val conjugate = FixComplex(16, -8)
    
    // 连接输入
    input.re.d.raw := io.real_in
    input.im.d.raw := io.imag_in
    
    // 计算共轭：实部不变，虚部取反
    conjugate.re.d.raw := input.re.d.raw
    conjugate.im.d.raw := ~input.im.d.raw + 1  // 取反加1（补码表示）
    
    // 连接输出
    io.real_out := conjugate.re.d.raw
    io.imag_out := conjugate.im.d.raw
  }
}

/**
 * 完整测试套件仿真
 */
object FixComplexCorrectTestSim {
  def main(args: Array[String]): Unit = {
    // 测试1：基本加法
    println("开始FixComplex加法测试...")
    SimConfig.withWave.compile(new FixComplexCorrectTest()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      // 测试复数加法：(1+2i) + (1+2i) = (2+4i)
      dut.io.enable #= true
      dut.io.real_in #= Math.round(1.0 * 128)  // 1.0
      dut.io.imag_in #= Math.round(2.0 * 128)  // 2.0
      dut.clockDomain.waitSampling(1)
      
      val real_sum = dut.io.real_out.toInt
      val imag_sum = dut.io.imag_out.toInt
      println(f"复数加法: (1+2i) + (1+2i) = ($real_sum/128 + ${imag_sum}/128i)")
      println(f"期望结果: (2+4i)")
      
      // 测试使能信号关闭
      dut.io.enable #= false
      dut.io.real_in #= Math.round(3.0 * 128)
      dut.io.imag_in #= Math.round(4.0 * 128)
      dut.clockDomain.waitSampling(1)
      
      val real_pass = dut.io.real_out.toInt
      val imag_pass = dut.io.imag_out.toInt
      println(f"使能关闭: 输出应为输入 ($real_pass/128 + ${imag_pass}/128i)")
    }
    
    // 测试2：复数乘法
    println("\n开始FixComplex乘法测试...")
    SimConfig.withWave.compile(new FixComplexMultCorrectTest()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      // 测试复数乘法：(1+2i) * (3+4i) = (3-8) + (4+6)i = -5 + 10i
      dut.io.real1 #= Math.round(1.0 * 128)
      dut.io.imag1 #= Math.round(2.0 * 128)
      dut.io.real2 #= Math.round(3.0 * 128)
      dut.io.imag2 #= Math.round(4.0 * 128)
      dut.clockDomain.waitSampling(1)
      
      val real_prod = dut.io.real_out.toInt
      val imag_prod = dut.io.imag_out.toInt
      println(f"复数乘法: (1+2i) * (3+4i) = ($real_prod/${128*128} + ${imag_prod}/${128*128}i)")
      println(f"期望结果: (-5+10i)")
      println(f"实际值: (${real_prod/(128.0*128.0)}%+6.3f + ${imag_prod/(128.0*128.0)}%+6.3fi)")
    }
    
    // 测试3：复数共轭
    println("\n开始FixComplex共轭测试...")
    SimConfig.withWave.compile(new FixComplexConjugateCorrectTest()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      // 测试复数共轭：(3+4i)* = 3-4i
      dut.io.real_in #= Math.round(3.0 * 128)
      dut.io.imag_in #= Math.round(4.0 * 128)
      dut.clockDomain.waitSampling(1)
      
      val real_conj = dut.io.real_out.toInt
      val imag_conj = dut.io.imag_out.toInt
      println(f"复数共轭: (3+4i)* = ($real_conj/128 + ${imag_conj}/128i)")
      println(f"期望结果: (3-4i)")
      println(f"实际值: (${real_conj/128.0}%+6.3f + ${imag_conj/128.0}%+6.3fi)")
    }
    
    println("\nFixComplex完整测试完成！")
    println("关键观察：")
    println("1. FixComplex包含re和im两个FixReal分量")
    println("2. 复数运算遵循数学规则，但需要硬件实现")
    println("3. 乘法自动扩展位宽")
    println("4. 共轭操作通过虚部取反实现")
  }
}